package io.gitee.twoke.generator.engine.impl.template.impl;

import cn.hutool.core.io.FileUtil;
import io.gitee.twoke.generator.engine.impl.context.Context;
import io.gitee.twoke.generator.engine.impl.persistence.entity.TemplateEntity;
import io.gitee.twoke.generator.engine.impl.persistence.entity.TemplateEntityManager;
import io.gitee.twoke.generator.engine.impl.persistence.entity.TemplateFileEntity;
import io.gitee.twoke.generator.engine.impl.persistence.entity.TemplateFileEntityManager;
import io.gitee.twoke.generator.engine.impl.template.CreateTemplateBuilder;
import io.gitee.twoke.generator.engine.impl.template.Template;
import cn.hutool.core.util.StrUtil;
import org.apache.ibatis.io.Resources;

import java.io.IOException;
import java.io.Serializable;
import java.net.URISyntaxException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;

public class CreateTemplateBuilderImpl implements CreateTemplateBuilder, Serializable {

    protected static final String DEFAULT_ENCODING = "UTF-8";
    protected transient TemplateServiceImpl templateService;
    protected transient TemplateEntityManager templateEntityManager;
    protected transient TemplateFileEntityManager templateFileEntityManager;

    private TemplateEntity template;
    private List<TemplateFileEntity> templateFileEntities;
    private List<String> templateFileNames;

    public CreateTemplateBuilderImpl(TemplateServiceImpl templateService) {
        this(templateService,
                Context.getGenerateEngineConfiguration().getTemplateEntityManager().create(),
                Context.getGenerateEngineConfiguration().getTemplateEntityManager(),
                Context.getGenerateEngineConfiguration().getTemplateFileEntityManager()
                );
    }


    public CreateTemplateBuilderImpl(TemplateServiceImpl templateService,
                                     TemplateEntity template,
                                     TemplateEntityManager templateEntityManager,
                                     TemplateFileEntityManager templateFileEntityManager
                               ) {
        this.templateService = templateService;
        this.template = template;
        this.templateEntityManager = templateEntityManager;
        this.templateFileEntityManager = templateFileEntityManager;
        this.templateFileEntities = new ArrayList<>();
        this.templateFileNames = new ArrayList<>();
    }

    @Override
    public CreateTemplateBuilder templateFileFromClassPath(String name, String resourcePath, String filenameExpression){
        try {
            String content = new String(FileUtil.readBytes(Resources.getResourceURL(resourcePath).getFile()),
                    StandardCharsets.UTF_8);
            return templateFile(name, content, filenameExpression);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public CreateTemplateBuilder templateFile(String name, String content, String filenameExpression) {
        if (StrUtil.isBlank(name)) {
            throw new IllegalArgumentException("Template File name cannot be blank");
        }
        if (StrUtil.isBlank(filenameExpression)) {
            throw new IllegalArgumentException("Template Filename expression cannot be null");
        }
        if (templateFileNames.contains(name)) {
            throw new IllegalArgumentException("Template File name has already been used");
        }
        TemplateFileEntity templateFileEntity = this.templateFileEntityManager.create();
        templateFileEntity.setName(name);
        templateFileEntity.setContent(content);
        templateFileEntity.setFilenameExpression(filenameExpression);
        this.templateFileEntities.add(templateFileEntity);
        this.templateFileNames.add(name);
        return this;
    }

    @Override
    public CreateTemplateBuilder name(String name) {
        this.template.setName(name);
        return this;
    }

    @Override
    public CreateTemplateBuilder description(String description) {
        this.template.setDescription(description);
        return this;
    }

    @Override
    public Template create() {
        if (StrUtil.isBlank(template.getName())) {
            throw new IllegalArgumentException("template name is empty");
        }
        return templateService.create(this);
    }

    public TemplateEntity getTemplate() {
        return template;
    }

    public List<TemplateFileEntity> getTemplateFileEntities() {
        return templateFileEntities;
    }
}
